﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace AnnieSharp
{
    /// <summary>
    /// 显示对象的容器类,可以将其他显示对象放入其中,是annie引擎的核心容器类.
    /// Sprite 类是基本显示列表构造块：一个可显示图形并且也可包含子项的显示列表节点。
    /// Sprite 对象与影片剪辑类似，但没有时间轴。Sprite 是不需要时间轴的对象的相应基类。
    /// 例如，Sprite 将是通常不使用时间轴的用户界面 (UI) 组件的逻辑基类
    /// </summary>
    public class Sprite : DisplayObject
    {
        public Sprite()
        {
            _instanceType = "annie.Sprite";
        }

        public override void Destroy() {

        }


        /// <summary>
        /// 是否可以让children接收鼠标事件
        /// 鼠标事件将不会往下冒泡
        /// </summary>
        public bool MouseChildren { get; set; }

        /// <summary>
        /// 显示对象的child列表
        /// </summary>
        public List<DisplayObject> Children { get; set; } = new List<DisplayObject>();

        public List<DisplayObject> RemoveChildren { get; set; } = new List<DisplayObject>();


        private bool _cacheAsBitmap = false;

        /// <summary>
        /// 是否缓存为位图
        /// 暂不支持缓存为位图
        /// </summary>
        public bool CacheAsBitmap { get {
                return _cacheAsBitmap;
            } set {
                if (value)
                {
                    throw (new Exception("未实现CacheAsBitmap"));
                }
                else
                {
                    Texture = null;
                    OffsetX = 0;
                    OffsetY = 0;
                }
                _cacheAsBitmap = value;
            } }



        /// <summary>
        /// 将一个现实对象添加到Sprite
        /// </summary>
        /// <param name="child"></param>
        public void AddChild(DisplayObject child)
        {
            AddChildAt(child, this.Children.Count);
        }

        /// <summary>
        /// 添加一个child到Sprite中并指定添加到哪个层级
        /// </summary>
        /// <param name="child">子现实对象</param>
        /// <param name="index">从0开始，添加的位置（层级）</param>
        public void AddChildAt(DisplayObject child, int index)
        {
            if (child == null) return;
            int len = 0;
            var cp = child.Parent;
            if (cp != null)
            {
                //先从父容器中移除当前对象
                //Sprite._removeFormParent(cp, child);
            }
            len = Children.Count;

            if (index < 0)
            {
                index = 0;
            }
            if (index > len)
            {
                index = len;
            }

            Children.Insert(index, child);

            if (cp != this)
            {
                child.ParentChanged = true;
                child.Stage = null;
                child.Parent = this;
                if(Stage!=null)
                {
                    if(UpdateState == UpdateState.Updating)
                    {
                        //被子级改了，遍历又过了，于是只能重新再遍历一次
                        //    s.stage.isReUpdate = true;
                        throw (new Exception("未实现被子级改了，遍历又过了，于是只能重新再遍历一次"));
                    }
                }
            }


        }

        /// <summary>
        /// 从Spirte中移除一个Child
        /// </summary>
        /// <param name="child"></param>
        public void RemoveChild(DisplayObject child)
        {
            Children.Remove(child);
            RemoveChildren.Add(child);
        }

        //全局遍历查找
        private static List<DisplayObject> GetElementByExpression(Func<string, bool> expression, Sprite root, bool isOnlyOne, bool isRecursive, List<DisplayObject> resultList)
        {
            if (root.Children != null)
            {
                var li = root.Children.Where(x => expression(x.Name)).ToList();
                if (resultList == null)
                {
                    resultList = new List<DisplayObject>();
                }

                if (li.Count > 0)
                {
                    if (isOnlyOne)
                    {
                        resultList.Add(li.First());
                    }
                    else
                    {
                        resultList.AddRange(li);
                    }

                }
                if (isRecursive)
                {
                    for (var i = 0; i < root.Children.Count; i++)
                    {
                        var currentChild = root.Children[i] as Sprite;
                        if (currentChild != null)
                        {
                            if (currentChild.Children.Count > 0)
                            {
                                GetElementByExpression(expression, currentChild, isOnlyOne, isRecursive, resultList);
                            }
                        }
                    }
                }
            }
            return resultList;
        }

        private static List<DisplayObject> GetElementByName(string name, Sprite root, bool isOnlyOne, bool isRecursive, List<DisplayObject> resultList)
        {
            return GetElementByExpression(x => x == name, root, isOnlyOne, isRecursive, resultList);
        }

        private static List<DisplayObject> GetElementByName(Regex reg, Sprite root, bool isOnlyOne, bool isRecursive, List<DisplayObject> resultList)
        {
            return GetElementByExpression(x => reg.IsMatch(x), root, isOnlyOne, isRecursive, resultList);
        }

        /// <summary>
        /// 通过给displayObject设置的名字来获取一个child,可以使用正则匹配查找
        /// </summary>
        /// <param name="name">对象的名称</param>
        /// <param name="isOnlyOne">默认为true,如果为true,只返回最先找到的对象,如果为false则会找到所有匹配的对象数组</param>
        /// <param name="isRecursive">false,如果为true,则会递归查找下去,而不只是查找当前对象中的child,child里的child也会找,依此类推</param>
        /// <returns></returns>
        public List<DisplayObject> GetChildByName(string name, bool isOnlyOne = true, bool isRecursive = false)
        {
            if (string.IsNullOrEmpty(name))
            {
                return null;
            }
            var resultList = new List<DisplayObject>();
            return GetElementByName(name, this, isOnlyOne, isRecursive, resultList);
        }

        /// <summary>
        /// 通过给displayObject设置的名字来获取一个child,可以使用正则匹配查找
        /// </summary>
        /// <param name="reg">对象的正则表达式</param>
        /// <param name="isOnlyOne">默认为true,如果为true,只返回最先找到的对象,如果为false则会找到所有匹配的对象数组</param>
        /// <param name="isRecursive">false,如果为true,则会递归查找下去,而不只是查找当前对象中的child,child里的child也会找,依此类推</param>
        /// <returns></returns>
        public List<DisplayObject> GetChildByName(Regex reg, bool isOnlyOne = true, bool isRecursive = false)
        {
            if (reg == null)
            {
                return null;
            }
            var resultList = new List<DisplayObject>();
            return GetElementByName(reg, this, isOnlyOne, isRecursive, resultList);
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="cp"></param>
        /// <param name="child"></param>
        private static void RemoveFromParent(Sprite cp, DisplayObject child)
        {
            if (cp.Children != null)
            {
                if (cp.Children.Contains(child))
                {
                    cp.Children.Remove(child);
                }
                else
                {
                    if (cp.RemoveChildren != null)
                    {
                        cp.RemoveChildren.Remove(child);
                    }
                }
            }
        }

        /// <summary>
        /// 获取Sprite中指定层级一个child
        /// </summary>
        /// <param name="index">从0开始</param>
        /// <returns></returns>
        public DisplayObject GetChildAt(int index)
        {
            if (Children.Count - 1 >= index)
            {
                return Children.ElementAt(index);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 获取Sprite中一个child所在的层级索引，找到则返回索引数，未找到则返回-1
        /// </summary>
        /// <param name="child"></param>
        /// <returns></returns>
        public int GetChildIndex(DisplayObject child)
        {
            return Children.IndexOf(child);
        }

        /// <summary>
        /// 交换两个显示对象的层级
        /// </summary>
        /// <param name="child1">显示对象1</param>
        /// <param name="child2">显示对象2</param>
        /// <returns></returns>
        public bool SwapChild(DisplayObject child1, DisplayObject child2)
        {
            if (Children.Contains(child1) && Children.Contains(child2))
            {
                var id1 = Children.IndexOf(child1);
                var id2 = Children.IndexOf(child2);
                Children[id1] = child2;
                Children[id2] = child1;
                return true;
            }
            return false;
        }

        /// <summary>
        /// 交换两个显示对象的层级
        /// </summary>
        /// <param name="index1">层级1</param>
        /// <param name="index2">层级2</param>
        /// <returns></returns>
        public bool SwapChild(int index1, int index2)
        {
            if (index1 >= 0 && index2 >= 0 && index1 < Children.Count && index2 < Children.Count)
            {
                var temp1 = Children[index1];
                var temp2 = Children[index2];
                Children[index1] = temp2;
                Children[index2] = temp1;
                return true;
            }
            return false;
        }

        /// <summary>
        /// 移除指定层级的子节点
        /// </summary>
        /// <param name="index"></param>
        public void RemoveChildrenAt(int index)
        {
            if(Children.Count - 1> index)
            {
                var child = Children[index];
                Children.Remove(child);
                RemoveChildren.Add(child);
            }
        }

        /// <summary>
        /// 移除所有的子节点
        /// </summary>
        public void RemoveAllChilren()
        {
            RemoveChildren.AddRange(Children);
            Children.RemoveAll(x => true);
        }



        public override void Render(IRender render)
        {
            UpdateState = UpdateState.NotUpdated;
            if (!Visible)
            {
                return;
            }
            if (CacheAsBitmap)
            {
                base.Render(render);
            }
            else
            {
                UpdateMatrix();
                DisplayObject child;
                DisplayObject maskObj = null;
                var len = Children.Count;
                for (var i = 0; i < len; i++)
                {
                    child = Children[i];
                    if(maskObj!=null)
                    {
                        if (child._isUseToMask > 0) continue;
                        if (child.Mask != null && child.Mask.Parent == child.Parent)
                        {
                            if (child.Mask != maskObj)
                            {
                                render.EndMask();
                                maskObj = child.Mask;
                                render.BeginMask(maskObj);
                            }
                        }
                        else
                        {
                            render.EndMask();
                            maskObj = null;
                        }
                    }
                    else
                    {
                        if (child.Mask != null && child.Mask.Parent == child.Parent)
                        {
                            maskObj = child.Mask;
                            render.BeginMask(maskObj);
                        }
                        child.Render(render);
                    }
                    if (maskObj!=null)
                    {
                        render.EndMask();
                    }
                    _UI.UF = false;
                    _UI.UM = false;
                    _UI.UA = false;
                }

            }
        }

        /// <summary>
        /// 更新状态0，未更新，1正在更新,2需要再次更新,3更新结束
        /// </summary>
        public UpdateState UpdateState { get; private set; } = UpdateState.NotUpdated;

        public override void UpdateEventAndScript(UpdateState callState)
        {

        }

    }
}
